package com.hexb.core.service;

import com.github.pagehelper.PageHelper;
import com.hexb.core.common.Page;
import com.hexb.core.enums.AscColors;
import com.hexb.core.exception.BusinessException;
import com.hexb.core.mapper.BaseMapper;
import com.hexb.core.model.QueryParameter;
import com.hexb.core.mybatis.entry.BatchUpdateParam;
import org.apache.log4j.Logger;

import java.util.List;
import java.util.Map;
import java.util.function.Function;

@SuppressWarnings("unused")
abstract public class AbstractBaseService<PK, T, Q extends QueryParameter> implements BaseService<PK, T, Q> {

    private Logger logger = Logger.getLogger(AbstractBaseService.class);

    @Override
    public Page<T> page(Q param, int pageNum, int pageSize) {
        return this.pageCommon(param.map(), pageNum, pageSize, getPrimaryMapper()::selectByMap);
    }

    @Override
    public Page<T> page(Map param, int pageNum, int pageSize) {
        return this.pageCommon(param, pageNum, pageSize, getPrimaryMapper()::selectByMap);
    }

    @Override
    public Page<T> page(T t, int pageNum, int pageSize) {
        return this.pageCommon(t, pageNum, pageSize, getPrimaryMapper()::select);
    }

    @Override
    public List<T> select(Q param) {
        return getPrimaryMapper().selectByMap(param.map());
    }


    @Override
    public List<T> select(Map param) {
        return getPrimaryMapper().selectByMap(param);
    }

    @Override
    public List<T> select(T t) {
        return getPrimaryMapper().select(t);
    }

    @Override
    public T selectOne(PK id) {
        return getPrimaryMapper().selectOne(id);
    }


    @Override
    public int insert(T t) {
        return getPrimaryMapper().insert(t);
    }

    @Override
    public int insertBatch(List<T> list) {
        return getPrimaryMapper().insertBatch(list);
    }

    @Override
    public int update(T t) {
        return getPrimaryMapper().update(t);
    }

    @Override
    public int updateBatchByMap(PK[] ids, Map<String, Object> params) {
        if (null == ids || ids.length < 1) {
            throw new BusinessException("批量更新时，参数ids不能为空", "PARAMETER_ERROR");
        }
        BatchUpdateParam<PK, Map<String, Object>> updateParams = new BatchUpdateParam<>();
        updateParams.setIds(ids);
        updateParams.setEntry(params);
        return getPrimaryMapper().updateBatchByMap(updateParams);
    }

    @Override
    public int updateByMap(Map<String, Object> param) {
        return getPrimaryMapper().updateByMap(param);
    }

    @Override
    public int updateBatch(PK[] ids, T params) {
        if (null == ids || ids.length < 1) {
            throw new BusinessException("批量更新时，参数ids不能为空", "PARAMETER_ERROR");
        }
        BatchUpdateParam<PK, T> updateParams = new BatchUpdateParam<>();
        updateParams.setIds(ids);
        updateParams.setEntry(params);
        return getPrimaryMapper().updateBatch(updateParams);
    }

    @Override
    public int delete(PK id) {
        return getPrimaryMapper().delete(id);
    }


    @Override
    public long count(Q param) {
        return getPrimaryMapper().count(param.map());
    }

    @Override
    public List<T> selectWithoutPk(T t) {
        return getPrimaryMapper().selectWithoutPK(t);
    }

    @Override
    public long count(T t) {
        return getPrimaryMapper().countByEntry(t);
    }

    @Override
    public long count(Map param) {
        return getPrimaryMapper().count(param);
    }

    @Override
    public int deleteBatch(PK[] ids) {
        if (null == ids || ids.length < 1) {
            throw new BusinessException("批量删除时，参数ids不能为空", "PARAMETER_ERROR");
        }
        return getPrimaryMapper().deleteBatch(ids);
    }

    public BaseMapper<PK, T> getPrimaryMapper() {
        return this.getDefaultMapper();
    }

    @Override
    public T selectOneByEntry(T t) {
        return getDefaultMapper().selectOneByEntry(t);
    }

    abstract protected BaseMapper<PK, T> getDefaultMapper();

    /**
     * @param func 获取列表方法
     */
    protected Page<T> pageCommon(Map map, int pageNum, int pageSize, Function<Map, List<T>> func) {
        return pageCommonAnyType(map, pageNum, pageSize, func);
    }

    /**
     * @param func 获取列表方法
     */
    protected Page<T> pageCommon(T param, int pageNum, int pageSize, Function<T, List<T>> func) {
        return pageCommonAnyType(param, pageNum, pageSize, func);
    }

    /**
     * @param func 获取列表方法
     */
    protected Page<T> pageCommon(Q param, int pageNum, int pageSize, Function<Q, List<T>> func) {
        return pageCommonAnyType(param, pageNum, pageSize, func);
    }

    protected <S, E> Page<E> pageCommonAnyType(S param, int pageNum, int pageSize, Function<S, List<E>> func) {
        return Pagination.pageCommonAnyType(param, pageNum, pageSize, func);
    }

    public void checkDefaultMapper() {
        if (this.getPrimaryMapper() == null) {
            logger.warn(String.format("%sSub Class Must be Implement #getDefaultMapper Method!%s", AscColors.RED, AscColors.END));
            throw new BusinessException(
                    "Sub Class Must be Implement #getDefaultMapper Method!",
                    "abstract_method_not_implemented");
        }
    }
}
